﻿#pragma once
#include "BracketWrapLayer.h"
#include "FormatedUtil.h"

class IFormatdTransfer
{
public:
	virtual ~IFormatdTransfer() = default;

	//从格式化字符串中转出
	virtual String dumpFormated(const String& elem_splitter, const String& wrapper) = 0;
	//从格式化字符串转入
	virtual void parseFormated(const String& formated_str, const String& elem_splitter, const String& noise) = 0;
};

template<typename Elem_T, typename Con_T = std::vector<Elem_T>>
class FormatedContainer :public IFormatdTransfer
{
public:
	typedef Elem_T ElementType;
	typedef Con_T ContainerType;

	FormatedContainer() :_bindContianer(false), _valsContainer(nullptr)
	{
	}
	FormatedContainer(Con_T& container) :FormatedContainer()
	{
		bindContaienr(container);
	}
	virtual ~FormatedContainer() override
	{
		releaseContainer();
	}

	//~IFormatdTransfer begin
	String dumpFormated(const String& elem_splitter, const String& wrapper) override
	{
		return FormatedUtil::dumpFormated(*getOrCreateContainer(), elem_splitter, wrapper);
	}
	void parseFormated(const String& formated_str, const String& elem_splitter, const String& noise) override
	{
		FormatedUtil::parseFormated(*getOrCreateContainer(), formated_str, elem_splitter, noise);
	}
	void parseFormated(BracketLayer* bracket_layer, const String& elem_splitter, const String& noise)
	{
		FormatedUtil::parseFormated(*getOrCreateContainer(), bracket_layer, elem_splitter, noise);
	}
	//~IFormatdTransfer end


	//使用指针和取引用如同直接操作内存态容器一样
	Con_T* operator->()
	{
		return getOrCreateContainer();
	}
	Con_T& operator*()
	{
		return *getOrCreateContainer();
	}

	//绑定外部创建的容器
	void bindContaienr(Con_T& container)
	{
		releaseContainer();
		_bindContianer = true;
		_valsContainer = &container;
	}
protected:
	Con_T* getOrCreateContainer()
	{
		if (!_valsContainer)
		{
			_valsContainer = new Con_T();
			_bindContianer = false;
		}
		return _valsContainer;
	}
	void releaseContainer()
	{
		if (!_bindContianer)
			ClearPtr(_valsContainer);
		_bindContianer = false;
	}
private:
	//内存态的容器是否来源于外部绑定的?
	bool _bindContianer;
	//内存态容器
	Con_T* _valsContainer;
};
